import { Camera, Canvas, director, find, Prefab,Node, Widget, math, instantiate, Script, Component, BatchingUtility } from "cc";
import { LoaderBundle } from "./LoaderBundle";
import { LoaderManager } from "./LoaderManager";
import { Message } from "./Message";
import { Singleton } from "./Singleton";
import { EffectManager } from "./EffectManager";

export enum UILayerIndex{
    BottomLayer=0,
    UIlayer,
    PopupLayer,
    TopLayer,
    SpareLayer,
    SpecialLayer,
    AdvLayer,
    UIRoot,
}
export enum UIWindowMessage{
    OpenUI="on_open_ui",        //打开UI
    CloseUI="on_close_ui",      //关闭UI
}

export class UIManager extends Singleton{
    private _canvas:Canvas|null;
    private _camera:Camera|null;
    private _layerList:Array<Node>|null;
    private _prefabmap:Map<string,Prefab>;
    private _nodemap:Map<string,Node>;

    get camera():Camera|null{return this._camera;}
    get root():Node|null{return this._canvas?.node;}
    
    protected init(): void {
        this._layerList=[];
        this._prefabmap=new Map();
        this._nodemap=new Map();
        
        this._canvas=find("Canvas")?.getComponent(Canvas)
        if(this._canvas){
            director.addPersistRootNode(this._canvas.node);//将UI根节点加入常驻节点
            this._camera=this._canvas.node.getChildByName("Camera")?.getComponent(Camera);
        }
        let createLayer=function(layerName:string):Node{
            let node:Node=new Node();
            node.name=layerName;    
            UIManager.getInstance().root.addChild(node);   
            let widget=node.addComponent(Widget); 
            widget.isAlignTop=widget.isAlignLeft=widget.isAlignBottom=widget.isAlignRight=true;
            widget.top=widget.left=widget.bottom=widget.right=0; 
            widget.alignMode=Widget.AlignMode.ON_WINDOW_RESIZE; 
            return node;
        }.bind(this)  
        let layerNames:Array<string>=["BottomLayer","UILayer","PopupLayer","TopLayer","SpareLayer","SpecialLayer","AdvLayer"]
        for(let i:number=0;i<layerNames.length;i++){
            var layer=createLayer(layerNames[i]); 
            this._layerList.push(layer); 
        }
    }
    /**
     * 获取层级节点
     * @param index 
     * @returns 
     */
    public getLayer(index:UILayerIndex=UILayerIndex.BottomLayer):Node{
        return this._layerList[index]
    }
    public show<T extends Component>(bundleName:string,path:string,parent:UILayerIndex|Node|null=null,comp:{new():T}=null,isEffect:boolean=true,duration: number=0.3,values?:any):Promise<Node>{
        return new Promise(async resolve=>{
            if(this._nodemap.has(path)){
                this.hide(path)
            }
            if(parent==null){
                parent=UILayerIndex.UIlayer;
            } 
            let root:Node=parent as Node; 
            if(typeof parent === "number"){
                root=this.getLayer(parent as number);
            } 
            let prefab:any=this._prefabmap.get(path);  
            if(!prefab){
                prefab = await LoaderManager.getInstance().getType(bundleName,path,Prefab)
                this._prefabmap.set(path,prefab)
            }
           
            let node:Node=instantiate(prefab);
            node.setParent(root)
            node.active=true;
            if(!this._nodemap.has(path)){
                this._nodemap.set(path,node) 
            }
            let c:T=null; 
            if(comp!=null){
                c=node.getComponent(comp)
                if(!c)c=node.addComponent(comp) 
                c["params"]=values 
            }
            // BatchingUtility.batchStaticModel(root,node); 
            if(isEffect){
                let main_node:Node = node.getChildByName("main")
                main_node && await EffectManager.getInstance().openUIWindow(main_node,duration)
            }
            Message.send(UIWindowMessage.OpenUI,node,path)
        })
    }
    /**
     * 释放已经显示的UI
     * @param path 
     * @returns s
     */
    hide(path:string,isEffect:boolean=true,duration: number=0.3):Promise<boolean>{ 
        return new Promise(async resolve=>{
            if(this._nodemap.has(path)){
                let node:Node = this._nodemap.get(path)  
                this._nodemap.delete(path)
                if(node!=null){
                    if(isEffect){
                        let main_node:Node = node.getChildByName("main")
                        main_node && await EffectManager.getInstance().openUIWindow(main_node,duration)
                    }
                    Message.send(UIWindowMessage.CloseUI,node,path)
                    node.destroy();
                    resolve(true); 
                    return 
                }
            }
            Message.send(UIWindowMessage.CloseUI,null,path)
            resolve(false);
        })
    }
    has(path?:string){
        return this._nodemap.has(path)
    }
    getUI(path:string):Promise<Node>{
        return new Promise(resolve=>{
            resolve(this._nodemap.get(path))
        })
    }

}